import asyncio
import logging
from pymodbus.server import StartAsyncSerialServer
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.device import ModbusDeviceIdentification
import threading
import time


# 配置串口参数
SERIAL_PORT = "COM1"  # Windows系统下的串口设备，Linux系统可能是/dev/ttyUSB0等
BAUDRATE = 9600
UNIT_ID = 1  # Modbus从站的设备地址

# 设置日志
logging.basicConfig(
    format="%(asctime)s [%(levelname)s] %(message)s",
    level=logging.DEBUG  # 调整日志级别为 DEBUG 以查看所有通信细节
)

# 启用 pymodbus 的通信日志
logging.getLogger("pymodbus").setLevel(logging.DEBUG)
logging.getLogger("pymodbus.server").setLevel(logging.DEBUG)
logging.getLogger("pymodbus.protocol").setLevel(logging.DEBUG)
logging.getLogger("pymodbus.transaction").setLevel(logging.DEBUG)

# 创建数据存储区

# 生成从 0x0000 开始递增 1 的列表，长度为 100
initial_values = [i for i in range(0x0000, 0x0000 + 1000)]

store = ModbusSlaveContext(
    di=ModbusSequentialDataBlock(1, [True, True, True, False]*25),  # 离散输入（Discrete Inputs）
    co=ModbusSequentialDataBlock(1, [True, True, False, False]*25),  # 线圈（Coils）
    hr=ModbusSequentialDataBlock(1, range(100)),  # 保持寄存器（Holding Registers）
    ir=ModbusSequentialDataBlock(1, range(100,200))   # 输入寄存器（Input Registers）
)

# 创建从站上下文
context = ModbusServerContext(slaves=store, single=True)

# 设备标识信息（可选）
identity = ModbusDeviceIdentification()
identity.VendorName = "MyCompany"
identity.ProductCode = "ModbusRTUServer"
identity.VendorUrl = "https://example.com"
identity.ProductName = "Modbus RTU Server"
identity.ModelName = "ModbusRTU v1.0"
identity.MajorMinorRevision = "1.0"

# 启动Modbus RTU服务器
async def run_server():
    logging.info(f"Starting Modbus RTU Server on {SERIAL_PORT} (Baudrate: {BAUDRATE}, Unit ID: {UNIT_ID})...")
    
    server = await StartAsyncSerialServer(
        context=context,
        identity=identity,
        port=SERIAL_PORT,
        baudrate=BAUDRATE,
        timeout=1,
        unit=UNIT_ID
    )
    try:
        await server.serve_forever()
    except asyncio.CancelledError:
        server.close()
        await server.wait_closed()


# 后台线程函数：动态更新寄存器值
def update_registers():
    i = 0
    while True:
        time.sleep(1)  # 每秒更新一次
        i += 1
        # 写入寄存器地址 0 的值
        context[0x00].setValues(3, 0, [i])  # 3 = HR，0 = 地址
        # log.info(f"写入保持寄存器[0] = {i}")

# 启动后台线程
t = threading.Thread(target=update_registers, daemon=True)
t.start()

if __name__ == "__main__":
    try:
        asyncio.run(run_server())
    except KeyboardInterrupt:
        logging.info("Server is shutting down...")